package de.carcophan.jimdb.jsf.mb;

import de.carcophan.jimdb.ejb.entites.Status;
import de.carcophan.jimdb.ejb.entites.UserMovies;
import de.carcophan.jimdb.ejb.entites.service.MovieFacade;
import de.carcophan.jimdb.ejb.entites.service.StatusFacade;
import de.carcophan.jimdb.ejb.entites.service.UserMoviesFacade;
import de.carcophan.jimdb.jsf.backing.StatusBackingBean;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.event.Event;
import javax.faces.model.DataModel;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;

public abstract class Controller extends AbstractController {

    @Inject
    Event<UserMovies> userMoviesEvent;
    @EJB
    private MovieFacade movieFacade;
    private UserMovies current = null;
    @NotNull
    private String selectedStatus;
    @Inject
    private StatusBackingBean statusBackingBean;

    @PostConstruct
    private void init() {
        this.selectedStatus = statusBackingBean.getStatuses().iterator().next().getMovieStatus();
    }

    public MovieFacade getMovieFacade() {
        return movieFacade;
    }

    public void setMovieFacade(MovieFacade movieFacade) {
        this.movieFacade = movieFacade;
    }

    public StatusFacade getStatusFacade() {
        return statusFacade;
    }

    public void setStatusFacade(StatusFacade statusFacade) {
        this.statusFacade = statusFacade;
    }

    public UserMoviesFacade getUserMoviesFacade() {
        return userMoviesFacade;
    }

    public void setUserMoviesFacade(UserMoviesFacade userMoviesFacade) {
        this.userMoviesFacade = userMoviesFacade;
    }
    @EJB
    private StatusFacade statusFacade;
    @EJB
    private UserMoviesFacade userMoviesFacade;
    private String sortBy;
    private String sortOrder;

    public abstract void saveSelectedMovie() throws Exception;

    public void sortMovies() {
        Map<String, String> requestParameterMap = getFacesContext().getExternalContext().getRequestParameterMap();
        String _sortOrder = requestParameterMap.get("sortOrder");
        String _sortBy = requestParameterMap.get("sortBy");
        if (_sortOrder != null) {
            this.sortOrder = _sortOrder;
        }
        if (_sortBy != null) {
            this.sortBy = _sortBy;
        }
        Comparator<UserMovies> comparator = new Comparator<UserMovies>() {

            public int compareTitle(UserMovies o1, UserMovies o2) {
                return o1.getMovie().getTitle().compareTo(o2.getMovie().getTitle());
            }

            public int compareYear(UserMovies o1, UserMovies o2) {
                return o1.getMovie().getYear() - o2.getMovie().getYear();
            }

            public int compareType(UserMovies o1, UserMovies o2) {
                int compareTo = 0;
                try {
                    compareTo = o1.getMovie().getType().getName().compareTo(o2.getMovie().getType().getName());
                } catch (NullPointerException e) {
                }
                return compareTo;
            }

            public int compareIMDBID(UserMovies o1, UserMovies o2) {
                return o1.getMovie().getIdForSite().compareTo(o2.getMovie().getIdForSite());
            }

            public int compareStatus(UserMovies o1, UserMovies o2) {
                return o1.getMovieStatus().getMovieStatus().compareTo(o2.getMovieStatus().getMovieStatus());
            }

            @Override
            public int compare(UserMovies o1, UserMovies o2) {
                try {
                    Method m = this.getClass().getMethod("compare" + sortBy, UserMovies.class, UserMovies.class);
                    int compareTo = (Integer) m.invoke(this, o1, o2);
                    return sortOrder.equals("ASC") ? compareTo : compareTo * -1;
                } catch (Exception ex) {
                    Logger.getLogger(SearchController.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 0;
            }
        };
        if (sortBy != null && sortOrder != null) {
            Collections.sort((List) this.getItems().getWrappedData(), comparator);
        }
    }

    public abstract DataModel<UserMovies> getItems();

    public abstract void refreshDataList(UserMovies um);

    public abstract void setItems(DataModel<UserMovies> items);

    public void changeStatus() {
        Status status = getStatusFacade().findByMovieStatus(this.selectedStatus);
        this.current = getItems().getRowData();
        current.setMovieStatus(status);
        getUserMoviesFacade().edit(current);
        userMoviesEvent.fire(current);
    }

    public void removeSelectedMovie() {
        this.current = getItems().getRowData();
        getUserMoviesFacade().remove(current);
        current.setId(null);
        userMoviesEvent.fire(current);
    }

    public UserMovies getCurrent() {
        return current;
    }

    public void setCurrent(UserMovies current) {
        this.current = current;
    }

    public String getSelectedStatus() {
        return selectedStatus;
    }

    public void setSelectedStatus(String selectedStatus) {
        this.selectedStatus = selectedStatus;
    }
}
